package advanced.sorm.utils;

import advanced.sorm.DBManager;
import advanced.sorm.TypeConvertor;
import advanced.sorm.bean.Columninfo;
import advanced.sorm.bean.JavaFieldGetSet;
import advanced.sorm.bean.TableInfo;

import java.io.*;
import java.util.ArrayList;
import java.util.Map;

/**
 * 封装了Java文件操作的常用的工具类
 */
public class JavaFileUtils {
    /**
     * 根据字段信息, 生成属性信息
     * 以及生成相应的get和set方法信息
     *
     * @param column
     * @param convertor
     * @return
     */
    public static JavaFieldGetSet createFieldGetSet(Columninfo column, TypeConvertor convertor) {
        JavaFieldGetSet jfs = new JavaFieldGetSet();
        String javaFieldType = convertor.databaseType2JavaType(column.getDataType());
        // \t 和\n 是为了让生成的格式更好看
        jfs.setFieldInfo("\tprivate " + javaFieldType + " " + column.getName() + ";\n");
        //生成get 方法
        StringBuilder getSrc = new StringBuilder();
        getSrc.append("\tpublic" + javaFieldType + " get" + STringUtils.firstChar2Upper(column.getName()) + "(){\n");
        getSrc.append("\treturn " + column.getName() + ";\n");
        getSrc.append("\t}\n");
        jfs.setGetInfo(getSrc.toString());
        //生成set方法

        StringBuilder setSrc = new StringBuilder();
        setSrc.append("\tpublic" + javaFieldType + " set" + STringUtils.firstChar2Upper(column.getName()) + "(" + javaFieldType + " " + column.getName() + "){\n");
        setSrc.append("\tthis." + column.getName() + "= " + column.getName() + ";\n");
        setSrc.append("\t}\n");
        jfs.setSetInfo(setSrc.toString());
        return jfs;
    }

    /**
     * 根据表信息, 生成Java类结构文件
     *
     * @param tableInfo
     * @param convertor
     * @return
     */
    public static String createJavaSrc(TableInfo tableInfo, TypeConvertor convertor) {
        StringBuilder src = new StringBuilder();
        Map<String, Columninfo> columns = tableInfo.getColumninfos();
        ArrayList<JavaFieldGetSet> javaFields = new ArrayList<>();
        for (Columninfo value : columns.values()) {
            javaFields.add(createFieldGetSet(value, convertor));
        }
        //先生成package 语句
        src.append(DBManager.getConf() + ";\n\n");
        //生成import语句
        src.append("import java.sql.*;\n");
        src.append("import java.util.*;\n\n");
        // 生成类声明语句
        src.append("public class " + STringUtils.firstChar2Upper(tableInfo.getTname()) + "{\n\n");
        //声称属性列表
        for (JavaFieldGetSet javaField : javaFields) {
            src.append(javaField.getFieldInfo());
        }
        src.append("\n\n");
        //生成构造器
        src.append("public " + STringUtils.firstChar2Upper(tableInfo.getTname()) + "(){}\n\n");
        //生成get方法列表
        for (JavaFieldGetSet javaField : javaFields) {
            src.append(javaField.getGetInfo());
        }
        src.append("\n\n");
        //生成set方法列表
        for (JavaFieldGetSet javaField : javaFields) {
            src.append(javaField.getSetInfo());
        }
        //        生成类结束
        src.append("\t}");
        return src.toString();
    }

    /**
     * 指定位置生成指定数据的文件
     */
    public static void createJavaPOFile(TableInfo tableInfo, TypeConvertor convertor) {
        String src = createJavaSrc(tableInfo, convertor);
        String srcPath = DBManager.getConf().getSrcPath() + "/";
        String poPackage = DBManager.getConf().getPoPackage();
        poPackage = poPackage.replaceAll("\\.", "/");
        File f = new File(srcPath + poPackage);
        if (f.exists()) f.mkdirs();//如果这个目录不粗在则创建这个目录
        System.out.println(f.getAbsolutePath() + "--------");

        BufferedWriter bw = null;
        try {
            bw = new BufferedWriter(new FileWriter(f + "/" + STringUtils.firstChar2Upper(tableInfo.getTname() + ".java")));
            bw.write(src);
            bw.flush();
            close(bw);
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("创建了Java类 " + tableInfo.getTname());
    }

    /**
     * 关闭资源
     *
     * @param args
     */
    private static void close(Closeable... args) {
        for (Closeable arg : args) {
            if (arg != null) {
                try {
                    arg.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
